using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using VRCPRServer.Models;

namespace VRCPRServer.WLan
{
    public class ManagementVM
    {
        private WlanClient Client;
        private WlanClient.WlanInterface WlanIface;
        private string NamePrefix = string.Empty;
        public delegate void SearchHandle(ObservableCollection<SSIDM> obj);
        public delegate void ConnectHandle(object name);
        public event ConnectHandle ConnectEvent;

        /// <summary>
        /// 当前WiFi列表
        /// </summary>
        public ObservableCollection<SSIDM> SSIDDic { get; set; }

        /// <summary>
        /// 当前WiFi
        /// </summary>
        public SSIDM ActiveWiFi { get; private set; }

        public ManagementVM()
        {
            SSIDDic = new ObservableCollection<SSIDM>();
            Client = new WlanClient();
            //NamePrefix = ConfigHelper.GetConfig("Dman_WIFI_Prefix");

            try
            {
                if (Client.Interfaces.Count() > 0)
                    WlanIface = Client.Interfaces[0];
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }

            if (WlanIface != null)
                WlanIface.WlanConnectionNotification += ConnectNotification;
        }

        #region 扫描当前WiFil列表
        /// <summary>
        /// 扫描当前WiFil列表
        /// </summary>
        /// <param name="callback"></param>
        public void ScanSSID(SearchHandle callback)
        {
            System.Threading.Tasks.Task.Run(() =>
            {
                foreach (WlanClient.WlanInterface wlanIface in Client.Interfaces)
                {
                    Wlan.WlanAvailableNetwork[] networks = wlanIface.GetAvailableNetworkList(0);
                    if (networks == null || networks.Length < 1)
                    {
                        SSIDDic.Clear();
                    }
                    else
                    {
                        Dictionary<string, SSIDM> keyValues = new Dictionary<string, SSIDM>();

                        foreach (Wlan.WlanAvailableNetwork network in networks)
                        {
                            SSIDM targetSSID = new SSIDM();
                            targetSSID.Itrerface = wlanIface;
                            targetSSID.SignalQuality = (int)network.wlanSignalQuality;
                            targetSSID.WiFiName = WlanHelper.GetStringForSSID(network.dot11Ssid);
                            targetSSID.DotllDefaultAuthAlgorithm = network.dot11DefaultAuthAlgorithm.ToString();
                            targetSSID.DotllDefaultCipherAlgorithm = network.dot11DefaultCipherAlgorithm.ToString();
                            targetSSID.Network = network;

                            if (!keyValues.ContainsKey(targetSSID.WiFiName))
                                keyValues.Add(targetSSID.WiFiName, targetSSID);

                            if (WlanHelper.HasProfile(targetSSID.Itrerface, WlanHelper.GetStringForSSID(network.dot11Ssid)))
                            {
                                targetSSID.IsConnected = true;
                            }
                        }

                        for (int i = 0; i < SSIDDic.Count; i++)
                        {
                            if (!keyValues.ContainsKey(SSIDDic[i].WiFiName))
                            {
                                SSIDDic.Remove(SSIDDic[i]);
                            }
                        }

                        List<string> names = keyValues.Keys.ToList();
                        for (int i = 0; i < keyValues.Count; i++)
                        {
                            if (SSIDDic.FirstOrDefault(item => item.WiFiName == names[i]) != null)
                                continue;

                            if (keyValues.TryGetValue(names[i], out SSIDM wIFISSID))
                            {
                                SSIDDic.Add(wIFISSID);
                            }
                        }

                        if (wlanIface.InterfaceState == Wlan.WlanInterfaceState.Connected && wlanIface.CurrentConnection.isState == Wlan.WlanInterfaceState.Connected)
                        {
                            string name = wlanIface.CurrentConnection.profileName;
                            SSIDM sSIDM = SSIDDic.FirstOrDefault(item => item.WiFiName == name);
                            if (sSIDM == null) return;
                            sSIDM.SSIDMsm = WlanNotificationCodeMsm.Connected;
                            sSIDM.SSIDAcm = WlanNotificationCodeAcm.ConnectionComplete;
                        }
                    }
                }

                callback?.BeginInvoke(SSIDDic, ar => { callback.EndInvoke(ar); }, null);
            });
        }

        #endregion

        #region 检测WiFi状态
        /// <summary>
        /// 当Wlan接口更改状连接态时的通知
        /// </summary>
        /// <param name="notifyData"></param>
        /// <param name="connNotifyData"></param>
        private void ConnectNotification(Wlan.WlanNotificationData notifyData, Wlan.WlanConnectionNotificationData connNotifyData)
        {
            try
            {
                SSIDM sSIDM = SSIDDic.FirstOrDefault(item => item.WiFiName == connNotifyData.profileName);
                if (sSIDM == null) return;

                if (notifyData.notificationSource == Wlan.WlanNotificationSource.MSM)
                {
                    sSIDM.SSIDMsm = (WlanNotificationCodeMsm)notifyData.NotificationCode;
                    //完成连接
                    if ((WlanNotificationCodeMsm)notifyData.NotificationCode == WlanNotificationCodeMsm.Connected)
                    {
                        //ConfigHelper.SetConfig("WIFI_CONFIG", sSIDM.WiFiName);
                    }
                }
                else if (notifyData.notificationSource == Wlan.WlanNotificationSource.ACM)   //连接
                {
                    WlanNotificationCodeAcm notificationCod = (WlanNotificationCodeAcm)notifyData.NotificationCode;
                    sSIDM.SSIDAcm = notificationCod;

                    if (notificationCod == WlanNotificationCodeAcm.ConnectionAttemptFail)
                    {
                        WlanIface.DeleteProfile(connNotifyData.profileName);
                    }
                }
                ConnectEvent?.Invoke(notifyData.NotificationCode);
                Console.WriteLine("{0}  {1}", notifyData.notificationSource, notifyData.NotificationCode);
            }
            catch (Exception e)
            {
                Debug.WriteLine(e);
            }
        }
        #endregion

        #region 无密码连接WiFi     
        /// <summary>
        /// 无需密码连接命令
        /// </summary>
        /// <param name="parameter">WiFi名称</param>
        public void ConnectWiFi(string wifiName)
        {
            SSIDM wIFISSID = SSIDDic.FirstOrDefault(item => item.WiFiName == wifiName);
            if (wIFISSID == null) return;

            if (WlanHelper.HasProfile(wIFISSID.Itrerface, WlanHelper.GetStringForSSID(wIFISSID.Network.dot11Ssid)))
            {
                wIFISSID.IsExpender = false;
                WlanHelper.ConnetWifi(wIFISSID.Itrerface, wIFISSID.Network);
            }
            else
            {
                for (int i = 0; i < SSIDDic.Count; i++)
                {
                    SSIDDic[i].IsExpender = false;
                }
                wIFISSID.IsExpender = true;
            }
        }

        /// <summary>
        /// 连接公开网络或者已经验证的网络
        /// </summary>
        /// <param name="wifiName">WiFi名称</param>
        public void Connect(string wifiName)
        {
            SSIDM wIFISSID = SSIDDic.FirstOrDefault(item => item.WiFiName == wifiName);
            if (wIFISSID == null) return;

            if (WlanHelper.HasProfile(wIFISSID.Itrerface, WlanHelper.GetStringForSSID(wIFISSID.Network.dot11Ssid)))
            {
                WlanHelper.ConnetWifi(wIFISSID.Itrerface, wIFISSID.Network);
            }
        }

        #endregion

        #region 密码连接WiFi
        /// <summary>
        /// 密码连接WiFi
        /// </summary>
        /// <param name="parameter">WiFi名称</param>
        public void PassWordConnect(string parameter)
        {
            if (parameter == string.Empty) return;

            string name = parameter.Split('\n')[0];
            SSIDM wIFISSID = SSIDDic.FirstOrDefault(item => item.WiFiName == name);
            if (wIFISSID == null) return;

            string passWord = parameter.Split('\n')[1];
            if (passWord.Length < 8)
            {
                wIFISSID.WiFiState = WiFiStatus.ConnectionFail;
                return;
            }

            if (!WlanHelper.HasProfile(wIFISSID.Itrerface, WlanHelper.GetStringForSSID(wIFISSID.Network.dot11Ssid)))
            {
                WlanHelper.ConnetWifi(wIFISSID.Itrerface, wIFISSID.Network, passWord);
            }
        }

        /// <summary>
        /// 连接未验证过的网络
        /// </summary>
        /// <param name="wifiName">WiFi名称</param>
        /// <param name="PassWord">WiFi密码</param>
        public void PassWordConnect(string wifiName, string PassWord)
        {
            SSIDM wIFISSID = SSIDDic.FirstOrDefault(item => item.WiFiName == wifiName);
            if (wIFISSID == null) return;
            {
                if (wIFISSID.Network.securityEnabled && !WlanHelper.HasProfile(wIFISSID.Itrerface, WlanHelper.GetStringForSSID(wIFISSID.Network.dot11Ssid)))
                {
                    WlanHelper.ConnetWifi(wIFISSID.Itrerface, wIFISSID.Network, PassWord);
                }
            }
        }
        #endregion

        /// <summary>
        /// 检测WiFi是否为模拟人WiFi（统一转换为小写进行对比）
        /// </summary>
        /// <param name="name">WiFi名称</param>
        /// <returns></returns>
        public bool ComperName(string name)
        {
            if (NamePrefix == string.Empty) return false;
            return name.ToLower().Contains(NamePrefix.ToLower());
        }

        /// <summary>
        /// </summary>
        public void RefreshWiFi()
        {
            ScanSSID(null);
        }

        /// <summary>
        /// 断开连接
        /// </summary>
        /// <param name="wifiName">WiFi名称</param>
        /// <returns>是否断开成功</returns>
        public bool DisConnect(string wifiName)
        {
            SSIDM wIFISSID = SSIDDic.FirstOrDefault(item => item.WiFiName == wifiName);
            if (wIFISSID != null)
            {
                wIFISSID.Itrerface.Disconnect();
            }
            return true;
        }

    }
}
